class_name StateMachine
extends State

## 当前状态名称
var current_state_name: String

## 子状态
var _states: Dictionary


func _init(init_name: String) -> void:
	super(init_name)
	current_state_name = "ghost"
	_states = {}


func get_state(path: String) -> State:
	if path.is_empty():
		return self
	else:
		var state_names := path.split(".")
		var from_state_name := state_names[0]
		state_names.remove_at(0)

		if not _states.has(from_state_name):
			Logger.error("Do not have a node with given name '%s'." % path)
			return null
		else:
			return _states[from_state_name].get_state(".".join(state_names))


func get_leaf_state() -> State:
	return _states[current_state_name]


func get_leaf_state_path() -> String:
	return name + "." + _states[current_state_name].get_leaf_state_path()


func dispatch_event(event_name: String) -> bool:
	if not super(event_name):
		if _states.has("any") and _states["any"].dispatch_event(event_name):
			return true
		
		if not _states.has(current_state_name):
			Logger.fatal("Do not have a state with given name '%s'." % current_state_name)
			return false
		
		if _states[current_state_name].dispatch_event(event_name):
			return true
		
	return false


func add_transition(source_state_name: String, transition: StateTransition) -> void:
	if transition == null:
		Logger.error("Transition should not be null.")
		return
	
	var state = _states.get(source_state_name)
	if state == null:
		Logger.error("Do not have a state with given name '%s'." % source_state_name)
		return
	
	if _transitions.has(transition.name):
		Logger.error("State already has the same transition with given name '%s'." % transition.name)
		return

	state._transitions[transition.name] = transition


func remove_transition(source_state_name: String, transition_name: String) -> void:
	var state = _states.get(source_state_name)
	if state == null:
		Logger.error("Do not have a state with given name '%s'." % source_state_name)
		return
	
	var transition = state._transitions.get(transition_name)
	if transition == null:
		Logger.error("State do not have this transition with given name '%s'." % transition_name)
		return
	
	state._transitions.erase(transition_name)


func activate_transition(source_state_name: String, transition_name: String) -> void:
	var state = _states.get(source_state_name)
	if state == null:
		Logger.error("Do not have a state with given name '%s'." % source_state_name)
		return
	
	var transition = state._transitions.get(transition_name)
	if transition == null:
		Logger.error("State do not have this transition with given name '%s'." % transition_name)
		return
	
	transition.active = true


func deactivate_transition(source_state_name: String, transition_name: String) -> void:
	var state = _states.get(source_state_name)
	if state == null:
		Logger.error("Do not have a state with given name '%s'." % source_state_name)
		return
	
	var transition = state._transitions.get(transition_name)
	if transition == null:
		Logger.error("State do not have this transition with given name '%s'." % transition_name)
		return
	
	transition.active = false


func add_state(state: State) -> void:
	if state == null:
		Logger.error("Added state should not be null.")
		return
	
	if _states.has(state.name):
		Logger.error("Already has a state with the given name '%s'." % state.name)
		return

	state.parent = self
	state.owner = owner
	_states[state.name] = state
	state.on_setup()


func remove_state(state: State) -> void:
	if state == null:
		Logger.error("Removed state should not be null.")
		return
	
	if not _states.has(state.name):
		Logger.error("Do not have a state with given name '%s'." % state.name)
		return

	if current_state_name == state.name:
		Logger.error("Can not remove current state '%s'." % state.name)
		return

	_states.erase(state.name)


func on_setup() -> void:
	add_state(State.new("ghost"))
	add_state(State.new("any"))
	super()


func on_enter() -> void:
	current_state_name = "ghost"

	super()

	if not _states.has(current_state_name):
		Logger.error("Current state '%s' is not in the state dictionary." % current_state_name)
		return

	_states[current_state_name].on_enter()


func on_update(delta: float) -> void:
	if try_all_transitions():
		return
	
	if _states.has("any"):
		_states["any"].on_update(delta)
	
	super(delta)

	if not _states.has(current_state_name):
		Logger.error("Current state '%s' is not in the state dictionary." % current_state_name)
		return

	_states[current_state_name].on_update(delta)


func on_exit() -> void:
	if not _states.has(current_state_name):
		Logger.error("Current state '%s' is not in the state dictionary." % current_state_name)
		return

	_states[current_state_name].on_exit()

	super()
